package hhs.scannerapp;

import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.nio.FloatBuffer;
import java.nio.ShortBuffer;
import java.util.Random;

import javax.microedition.khronos.opengles.GL10;

import android.graphics.Color;
import android.util.Log;

public class Cube {
	float width;
	float height;
	float depth;
	
	FloatBuffer colorBuffer;
	FloatBuffer vertexBuffer;
	ShortBuffer indexBuffer;
	ShortBuffer topIndBuffer;
	FloatBuffer texBuffer;
	
	float[] vertices = new float[3*(8+2)]; //And another "edge" to allow texture wrapping
	short[] indexes = new short[2*4*3];
	short[] topIndexes = new short[2*2];
	float[] texPoints = new float[2*8];
	
	int[] textures = new int[1]; //Store the texture pointer
	
	private boolean ready = false;

	public void instantiate(float _width, float _height, float _depth) {
		depth = _depth;
		width = _width;
		height = _height;
		
		makeVertexBuffer();
		makeIndexBuffer();
		makeTopIndBuffer();
		makeTexBuffer();
		ready = true;
	}

	private void makeVertexBuffer() {
		int counter = 0;
		for(int i = 0; i < 2; i++) {
			float isign = (i == 0 ? 1 : -1);
			for(int j = 0; j < 2; j++) {
				float jsign = (j == 0 ? 1 : -1);
				for(int k = 0; k < 2; k++) {
					float ksign = (k == 0 ? 1 : -1);
					vertices[3*counter] = isign*width/2.0f;
					vertices[3*counter+1] = jsign*height/2.0f;
					vertices[3*counter+2] = ksign*depth/2.0f;	
					
					counter++;
				}
			}
		}	
		
		for(int i = 0; i < 3; i++) {
			vertices[i+8*3] = vertices[i];
			vertices[3+i+8*3] = vertices[i+6];
		}
		
		ByteBuffer byteBuffer = ByteBuffer.allocateDirect(vertices.length*4);
		byteBuffer.order(ByteOrder.nativeOrder());
		vertexBuffer = byteBuffer.asFloatBuffer();	
		vertexBuffer.put(vertices);
		vertexBuffer.position(0);
	}
	
	private void makeIndexBuffer() {
		indexes = new short[]
				{0, 2, 1, 
				 1, 2, 3, 
				 1, 3, 7, 
				 1, 7, 5, 
				 5, 7, 6, 
				 5, 6, 4, 
				 4, 6, 9, 
				 4, 9, 8};
		
		ByteBuffer byteBuffer = ByteBuffer.allocateDirect(indexes.length*4);
		byteBuffer.order(ByteOrder.nativeOrder());
		indexBuffer = byteBuffer.asShortBuffer();	
		indexBuffer.put(indexes);
		indexBuffer.position(0);
	}
	
	private void makeTopIndBuffer() {
		topIndexes = new short[]
				{0, 1, 4, 
				 1, 5, 4, 
				 3, 2, 6, 
				 6, 7, 3};
		
		ByteBuffer byteBuffer = ByteBuffer.allocateDirect(topIndexes.length*4);
		byteBuffer.order(ByteOrder.nativeOrder());
		topIndBuffer = byteBuffer.asShortBuffer();	
		topIndBuffer.put(topIndexes);
		topIndBuffer.position(0);		
	}
	
	private void makeTexBuffer() {
		float length = 2*width+2*depth;
		float d1 = depth/length;
		float d2 = d1+width/length;
		float d3 = d2+depth/length;
		texPoints = new float[] 
				{0f, 0f, //0-
				 d1, 0f, //1
				 
				 0f, 1f, //2-
				 d1, 1f, //3
				 
				 d3, 0f, //4
				 d2, 0f, //5
				 
				 d3, 1f, //6
				 d2, 1f, //7
				 
				 1f, 0f, //8 Extra edge
				 1f, 1f}; //9 Extra edge
		
		ByteBuffer byteBuffer = ByteBuffer.allocateDirect(texPoints.length*4);
		byteBuffer.order(ByteOrder.nativeOrder());
		texBuffer = byteBuffer.asFloatBuffer();		
		texBuffer.put(texPoints);
		texBuffer.position(0);
	}
	
	
	public void makeColors(){
		//6 faces * 4 points * 4 values for color(rgba) * 4 bytes in a float
		ByteBuffer byteBuffer11 = ByteBuffer.allocateDirect(6*4*4*4);
		byteBuffer11.order(ByteOrder.nativeOrder());
		colorBuffer = byteBuffer11.asFloatBuffer();
		colorBuffer.clear();
		colorBuffer.position(0);

		//4 values for color(rgba) * 6 faces * 4 points per face
		float[] colors = new float[4*4*6];
		
		for(int i = 0; i < colors.length; i+=4) {
			Random random = new Random();
			float a = random.nextFloat(), b=random.nextFloat(), c=random.nextFloat();
			colors[i] = a;
			colors[i+1] =b;
			colors[i+2] = c;
			colors[i+3] = 1.0f;
		}	

		colorBuffer.put(colors);
		colorBuffer.position(0);

	}
	
	public void makeColors(int color){
		Log.e("Color", Color.red(color) + " "+Color.green(color) + " "+Color.blue(color) + " "+Color.alpha(color));
		float r = Color.red(color)/255, g = Color.green(color)/255, b = Color.blue(color)/255, a = Color.alpha(color)/255;
	
		//6 faces * 4 points * 4 values for color(rgba) * 4 bytes in a float
		ByteBuffer byteBuffer11 = ByteBuffer.allocateDirect(6*4*4*4);
		byteBuffer11.order(ByteOrder.nativeOrder());
		colorBuffer = byteBuffer11.asFloatBuffer();
		colorBuffer.clear();
		colorBuffer.position(0);

		//4 values for color(rgba) * 6 faces * 4 points per face
		float[] colors = new float[4*4*6];
		

		for(int i = 0; i < colors.length; i+=4) {
			float fi = (float)i;
			colors[i] = ((fi*r)%colors.length)/(colors.length);
			colors[i+1] = ((fi*g)%colors.length)/(colors.length);
			colors[i+2] = ((fi*b)%colors.length)/(colors.length);
			colors[i+3] = ((fi*a)%colors.length)/(colors.length);
		}	
		

		colorBuffer.put(colors);
		colorBuffer.position(0);

	}
	
	public void draw(GL10 gl, String type){
		if(ready) {
			if(type.equalsIgnoreCase("texture")){
				gl.glColor4f(1f,1f,1f,1f);
				gl.glEnable(GL10.GL_TEXTURE_2D);
				gl.glBindTexture(GL10.GL_TEXTURE_2D, textures[0]);
				gl.glEnableClientState(GL10.GL_VERTEX_ARRAY);
				gl.glEnableClientState(GL10.GL_TEXTURE_COORD_ARRAY);
				gl.glVertexPointer(3, GL10.GL_FLOAT, 0, vertexBuffer);
				gl.glTexCoordPointer(2, GL10.GL_FLOAT, 0, texBuffer);
				gl.glDrawElements(GL10.GL_TRIANGLES, indexBuffer.capacity(), GL10.GL_UNSIGNED_SHORT, indexBuffer);
				gl.glDisableClientState(GL10.GL_TEXTURE_COORD_ARRAY);			
				gl.glDrawElements(GL10.GL_TRIANGLES, topIndBuffer.capacity(), GL10.GL_UNSIGNED_SHORT, topIndBuffer);
				gl.glDisableClientState(GL10.GL_VERTEX_ARRAY);
			}

			else if(type.equalsIgnoreCase("color")||type.equalsIgnoreCase("randomcolor")){
				gl.glEnableClientState(GL10.GL_VERTEX_ARRAY);
				gl.glEnableClientState(GL10.GL_COLOR_ARRAY);
				gl.glShadeModel(GL10.GL_FLAT);
				gl.glColorPointer(4, GL10.GL_FLOAT, 0, colorBuffer);
				gl.glVertexPointer(3, GL10.GL_FLOAT, 0, vertexBuffer);
				gl.glDrawElements(GL10.GL_TRIANGLES, indexBuffer.capacity(), GL10.GL_UNSIGNED_SHORT, indexBuffer);		
				gl.glDrawElements(GL10.GL_TRIANGLES, topIndBuffer.capacity(), GL10.GL_UNSIGNED_SHORT, topIndBuffer);
				gl.glDisableClientState(GL10.GL_VERTEX_ARRAY);
				gl.glDisableClientState(GL10.GL_COLOR_ARRAY);
			}
			
			else{
				gl.glEnableClientState(GL10.GL_VERTEX_ARRAY);
				gl.glVertexPointer(3, GL10.GL_FLOAT, 0, vertexBuffer);
				gl.glDrawElements(GL10.GL_TRIANGLES, indexBuffer.capacity(), GL10.GL_UNSIGNED_SHORT, indexBuffer);		
				gl.glDrawElements(GL10.GL_TRIANGLES, topIndBuffer.capacity(), GL10.GL_UNSIGNED_SHORT, topIndBuffer);
				gl.glDisableClientState(GL10.GL_VERTEX_ARRAY);
			}
		}
	}
}
